﻿using IP2Region.Net.XDB;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Polaris.Common;
using Polaris.Common.RedisHelper;
using Polaris.Domain.Interfaces.Admin;
using Polaris.Domain.Model.DbEntity;
using Polaris.Domain.Model.Dto.Sys_Dictionary.Response;
using Polaris.Domain.Model.Dto.Sys_Menu.Request;
using Polaris.Domain.Model.Dto.Sys_Menu.Response;
using Polaris.Domain.Model.Entity.Base;
using Polaris.Domain.Model.Entity.Exception;
using Polaris.Domain.Model.Enum;
using Polaris.Domain.Repository.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace Polaris.Infrastructure.DomainService.Admin
{
    public class Sys_MenuService : ISys_Menu
    {
        private readonly IBaseRepository<Sys_Menu> _menu;

        public Sys_MenuService(IBaseRepository<Sys_Menu> menu)
        {
            _menu = menu;
        }

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="create"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task CreateMenu(CreateMenuRequest create, Guid? userId)
        {
            try
            {
                var menu = new Sys_Menu()
                {
                    Id = Guid.NewGuid(),
                    Name = create.Name,
                    MenuIcon = create.MenuIcon,
                    MenuType = (int)create.MenuType,
                    PageUrl = create.PageUrl,
                    Router = create.Router,
                    ParentID = create.ParentID,
                    Sort = create.Sort,
                    Enable = create.Enable,
                    IsDelete = false,
                    CreateBy = userId,
                    CreatedTime = DateTime.Now,
                };
                await _menu.AddEntityAsync(menu);
                await _menu.CommitAsync();

                RedisHelper.SetStringKey($"{menu.Id}-Menu", JsonConvert.SerializeObject(menu), TimeSpan.FromMinutes(5));
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 修改菜单
        /// </summary>
        /// <param name="update"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task UpdateMenu(UpdateMenuRequest update, Guid? userId)
        {
            try
            {
                var menu = await _menu.WhereLoadEntityAsNoTrackingAsync(d => d.Id.ToString() == update.Id) ??
                           throw new CustomException(ResultCode.NO_DATA, $"菜单中找不到Id是 {update.Id} 的数据");

                if (string.IsNullOrEmpty(menu.ParentID.ToString()) && !string.IsNullOrEmpty(update.ParentID.ToString()))
                {
                    throw new CustomException(ResultCode.FAIL, "顶级菜单的父级必须为空");
                }

                menu.Sort = update.Sort;
                menu.Name = update.Name;
                menu.MenuIcon = update.MenuIcon;
                menu.PageUrl = update.PageUrl;
                menu.Router = update.Router;
                menu.ParentID = update.ParentID;
                menu.Enable = update.Enable;
                menu.MenuType = (int)update.MenuType;
                menu.UpdatedBy = userId;
                menu.UpdatedTime = DateTime.Now;
                _menu.UpdateEntity(menu);
                await _menu.CommitAsync();
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 删除菜单，逻辑删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteMenu(string id, Guid? userId)
        {
            try
            {
                var menu = await _menu.WhereLoadEntityAsNoTrackingAsync(d => d.Id.ToString() == id) ??
                          throw new CustomException(ResultCode.NO_DATA, $"菜单中找不到Id是 {id} 的数据");

                menu.IsDelete = true;
                menu.UpdatedBy = userId;
                menu.UpdatedTime = DateTime.Now;
                _menu.UpdateEntity(menu);
                await _menu.CommitAsync();
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<List<MenuTree>> GetMenuList(SearchMenuRequest search)
        {
            try
            {
                Expression<Func<Sys_Menu, bool>> where = e => e.IsDelete == false;
                where = where.AndIF(search.MenuName != null, e => e.Name.Contains(search.MenuName));
                where = where.AndIF(search.MenuType != null, e => e.MenuType == (int)search.MenuType);
                var menuList = await _menu.WhereLoadEntityListAsNoTrackingAsync(where);
                menuList = menuList.OrderByDescending(d => d.Sort).ThenBy(d => d.Name).ToList();

                var treeList = new List<MenuTree>();
                foreach (var item in menuList)
                {
                    if (string.IsNullOrEmpty(item.ParentID?.ToString()))
                    {
                        treeList.Add(new MenuTree()
                        {
                            ParentID = null,
                            Name = item.Name,
                            Id = item.Id.ToString(),
                            Icon = item.MenuIcon,
                            Children = GetMenuTreeChilden(item.Id, menuList, true)
                        });
                    }
                }

                return treeList;
            }
            catch (Exception ex)
            {
                throw new CustomException(ResultCode.FAIL, ex.Message);
            }
        }


        /// <summary>
        /// 根据id获取菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<MenuInfoResponse> GetMenuById(Guid id)
        {
            //var redis = RedisHelper.GetStringKey($"{id}-Menu");
            //var result = new MenuInfoResponse();
            //if (!string.IsNullOrEmpty(redis))
            //{
            //    var data = JsonConvert.DeserializeObject<Sys_Menu>(redis);
            //    result.CreateBy = data.CreateBy?.ToString();
            //    result.CreatedTime = data.CreatedTime;
            //    result.Id = data.Id;
            //    result.UpdatedBy = data.UpdatedBy.ToString();
            //    result.UpdatedTime = data.UpdatedTime;
            //    result.Sort = data.Sort;
            //    result.MenuIcon = data.MenuIcon;
            //    result.MenuType = data.MenuType;
            //    result.Name = data.Name;
            //    result.PageUrl = data.PageUrl;
            //    result.ParentID = data.ParentID?.ToString();
            //    result.Router = data.Router;
            //    result.Enable = data.Enable;
            //}
            //else
            //{
            var result = await _menu.QueryAll(d => d.Id == id).Select(d => new MenuInfoResponse
            {
                Id = d.Id,
                Name = d.Name,
                CreateBy = d.CreateBy.ToString(),
                CreatedTime = d.CreatedTime,
                UpdatedBy = d.UpdatedBy.ToString(),
                UpdatedTime = d.UpdatedTime,
                MenuIcon = d.MenuIcon,
                MenuType = d.MenuType,
                Enable = d.Enable,
                PageUrl = d.PageUrl,
                ParentID = d.ParentID.ToString(),
                Router = d.Router,
                Sort = d.Sort,
            }).FirstOrDefaultAsync();
            //}
            return result;
        }

        /// <summary>
        /// 获取树形菜单
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<List<MenuTree>> GetMenuTree()
        {
            var menuAll = await _menu.WhereLoadEntityListAsNoTrackingAsync(d => !d.IsDelete);

            var treeList = new List<MenuTree>();
            foreach (var item in menuAll)
            {
                if (string.IsNullOrEmpty(item.ParentID?.ToString()))
                {
                    treeList.Add(new MenuTree()
                    {
                        ParentID = null,
                        Name = item.Name,
                        Id = item.Id.ToString(),
                        Children = GetMenuTreeChilden(item.Id, menuAll)
                    });
                }
            }

            return treeList;
        }

        /// <summary>
        /// 递归查询出子级
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="menuList"></param>
        /// <param name="quyerIcon"></param>
        /// <returns></returns>
        private List<MenuTree>? GetMenuTreeChilden(Guid pid, List<Sys_Menu> menuList, bool quyerIcon = false)
        {
            var treeList = new List<MenuTree>();
            foreach (var item in menuList)
            {
                if (item.ParentID == pid)
                {
                    treeList.Add(new MenuTree()
                    {
                        ParentID = item.ParentID.ToString(),
                        Name = item.Name,
                        Id = item.Id.ToString(),
                        Icon = quyerIcon ? item.MenuIcon : null,
                        Children = GetMenuTreeChilden(item.Id, menuList)
                    });
                }
            }
            return treeList.Count > 0 ? treeList : null;
        }
    }
}
